#include "preprocess.h"
#include <regex.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define MAX_PATTERNS 22

typedef struct {
    regex_t regex;
    const char* pattern;
} CachedRegex;

static CachedRegex regex_cache[MAX_PATTERNS];
static bool initialized = false;

// 新的替换函数实现
static char* replace_pattern(const char* line, regex_t* regex) {
    const char* current = line;
    char* result = malloc(1);
    if (result == NULL) {
        return NULL;
    }
    result[0] = '\0';
    size_t result_len = 0;
    regmatch_t matches[1];

    while (regexec(regex, current, 1, matches, 0) == 0) {
        int start = matches[0].rm_so;
        int end = matches[0].rm_eo;
        if (start == -1 || end == -1) {
            break;
        }
        
        // 计算匹配之前的前缀长度
        size_t prefix_len = start;
        char* prefix = malloc(prefix_len + 1);
        if (prefix == NULL) {
            free(result);
            return NULL;
        }
        strncpy(prefix, current, prefix_len);
        prefix[prefix_len] = '\0';

        // 重新分配结果内存并追加前缀
        result = realloc(result, result_len + prefix_len + 4 + 1); // 4 for "<*>"
        if (result == NULL) {
            free(prefix);
            return NULL;
        }
        strcpy(result + result_len, prefix);
        result_len += prefix_len;
        free(prefix);

        // 追加"<*>"
        strcpy(result + result_len, "<*>");
        result_len += 3;

        // 移动current到匹配之后
        current += end;
    }
    
    // 追加剩余部分
    size_t remaining_len = strlen(current);
    result = realloc(result, result_len + remaining_len + 1);
    if (result == NULL) {
        return NULL;
    }
    strcpy(result + result_len, current);
    return result;
}

bool preprocess_init(void) {
    if (initialized) return true;

    const char* patterns[MAX_PATTERNS] = {
        OPSTACK_SPECIAL_VARS_PATTERN2, // OpenStack前缀
        OPENSTACK_UUID_PATTERN, // OpenStack UUID模式
        TIMESTAMP_WITH_YEAR_PATTERN, // 带年份的时间戳
        MACTIME,       // Mac时间戳模式
        HEALTHAPP_TIMESTAMP_PATTERN, // HealthApp时间戳模式
        MAC_HOSTNAME_PATTERN, // Mac主机名模式
        IP_V4V6_PATTERN, // IPv4和IPv6地址模式
        IPV6_ADDRESS_PATTERN, // 仅IPv6地址模式（十六进制）
        WINDOWS_REGISTRY_HIVE_PATH_PATTERN,
        WINDOWS_PATH_PATTERN,
        URL_PATTERN,                   // 网址模式
        PATH_PATTERN,                  // 路径
        HADOOP_SPECIAL_VARS_PATTERN , // XXX_等特定变量
        HADOOP_SPECIAL_VARS_PATTERN2 , // type=等特定变量
        USER_PATTERN,                  // user后面的字符串
        HEX_PATTERN,                   // 十六进制数字
        TIMESTAMP_MONTH_PATTERN,       // 时间戳（有月份）
        TIMESTAMP_NO_MONTH_PATTERN,    // 时间戳（无月份）
        IP_PATTERN,                    // IP地址
        HOSTNAME_PATTERN,              // 主机名
        DECIMAL_NUMBER_PATTERN,    //整数部分和小数部分至少各1位
        NUMBER_PATTERN                 // 数字序列
    };

    for (int i = 0; i < MAX_PATTERNS; i++) {
        int ret = regcomp(&regex_cache[i].regex, patterns[i], REG_EXTENDED);
        if (ret != 0) {
            char error_msg[256];
            regerror(ret, &regex_cache[i].regex, error_msg, sizeof(error_msg));
            fprintf(stderr, "Failed to compile regex %s: %s\n", patterns[i], error_msg);
            // Cleanup already compiled regexes
            for (int j = 0; j < i; j++) {
                regfree(&regex_cache[j].regex);
            }
            return false;
        }
        regex_cache[i].pattern = patterns[i];
    }

    initialized = true;
    return true;
}

void preprocess_cleanup(void) {
    if (!initialized) return;

    for (int i = 0; i < MAX_PATTERNS; i++) {
        regfree(&regex_cache[i].regex);
    }
    initialized = false;
}

char* preprocess_log(const char* log_line) {
    if (!initialized) {
        if (!preprocess_init()) {
            return NULL;
        }
    }

    char* processed = strdup(log_line);
    if (!processed) return NULL;

    // 按特定顺序应用正则表达式
    for (int i = 0; i < MAX_PATTERNS; i++) {
        char* new_processed = replace_pattern(processed, &regex_cache[i].regex);
        if (!new_processed) {
            free(processed);
            return NULL;
        }
        free(processed);
        processed = new_processed;
    }

    return processed;
}

/*#include "preprocess.h"
#include <regex.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

typedef struct {
    regex_t regex;
    const char* pattern;
} CachedRegex;

static CachedRegex regex_cache[MAX_PATTERNS];
static bool initialized = false;

// 新的替换函数实现
static char* replace_pattern(const char* line, regex_t* regex) {
    const char* current = line;
    char* result = malloc(1);
    if (result == NULL) {
        return NULL;
    }
    result[0] = '\0';
    size_t result_len = 0;
    regmatch_t matches[1];

    while (regexec(regex, current, 1, matches, 0) == 0) {
        int start = matches[0].rm_so;
        int end = matches[0].rm_eo;
        if (start == -1 || end == -1) {
            break;
        }
        
        // 计算匹配之前的前缀长度
        size_t prefix_len = start;
        char* prefix = malloc(prefix_len + 1);
        if (prefix == NULL) {
            free(result);
            return NULL;
        }
        strncpy(prefix, current, prefix_len);
        prefix[prefix_len] = '\0';

        // 重新分配结果内存并追加前缀
        result = realloc(result, result_len + prefix_len + 4 + 1); // 4 for "<*>"
        if (result == NULL) {
            free(prefix);
            return NULL;
        }
        strcpy(result + result_len, prefix);
        result_len += prefix_len;
        free(prefix);

        // 追加"<*>"
        strcpy(result + result_len, "<*>");
        result_len += 3;

        // 移动current到匹配之后
        current += end;
    }
    
    // 追加剩余部分
    size_t remaining_len = strlen(current);
    result = realloc(result, result_len + remaining_len + 1);
    if (result == NULL) {
        return NULL;
    }
    strcpy(result + result_len, current);
    return result;
}

bool preprocess_init(void) {
    if (initialized) return true;

    const char* patterns[MAX_PATTERNS] = {
        URL_PATTERN,                   // 网址模式
        WIN_DATETIME_PATTERN,          // Windows日期时间模式
        SPARK_TIME_PATTERN,            // Spark时间格式
        WIN_TIMESTAMP_PATTERN,         // Windows时间戳模式
        TIMESTAMP_MONTH_PATTERN,       // 时间戳（有月份）
        TIMESTAMP_NO_MONTH_PATTERN,    // 时间戳（无月份）
        IP_PATTERN,                    // IP地址
        IPV6_PATTERN,                  // IPv6地址
        HOSTNAME_PATTERN,              // 主机名
        PATH_PATTERN,                  // 路径
        WIN_PATH_PATTERN,              // Windows路径
        GUID_PATTERN,                  // GUID
        VERSION_PATTERN,               // 版本号
        HEX_PATTERN,                   // 十六进制数
        WIN_ERROR_PATTERN,             // Windows错误代码
        USER_LIST_PATTERN,             // 用户列表
        NUMBER_PATTERN                 // 数字序列
    };

    for (int i = 0; i < MAX_PATTERNS; i++) {
        int ret = regcomp(&regex_cache[i].regex, patterns[i], REG_EXTENDED);
        if (ret != 0) {
            char error_msg[100];
            regerror(ret, &regex_cache[i].regex, error_msg, sizeof(error_msg));
            fprintf(stderr, "Failed to compile regex %s: %s\n", patterns[i], error_msg);
            // Cleanup already compiled regexes
            for (int j = 0; j < i; j++) {
                regfree(&regex_cache[j].regex);
            }
            return false;
        }
        regex_cache[i].pattern = patterns[i];
    }

    initialized = true;
    return true;
}

void preprocess_cleanup(void) {
    if (!initialized) return;

    for (int i = 0; i < MAX_PATTERNS; i++) {
        regfree(&regex_cache[i].regex);
    }
    initialized = false;
}

char* preprocess_log(const char* log_line) {
    if (!initialized) {
        if (!preprocess_init()) {
            return NULL;
        }
    }

    char* processed = strdup(log_line);
    if (!processed) return NULL;

    // 按特定顺序应用正则表达式（与您的新代码顺序一致）
    for (int i = 0; i < MAX_PATTERNS; i++) {
        char* new_processed = replace_pattern(processed, &regex_cache[i].regex);
        if (!new_processed) {
            free(processed);
            return NULL;
        }
        free(processed);
        processed = new_processed;
    }

    return processed;
}*/